package io.demo.petstore.web;

import static org.assertj.core.api.Assertions.assertThat;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import io.demo.petstore.account.Account;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.hateoas.VndErrors;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

/**
 * @author lijinting01
 */
@Slf4j
public class RegisterIT {

  private static final String REGISTER_URL = "http://localhost:8080/account/register";

  private ObjectMapper objectMapper;

  private TestRestTemplate restTemplate;

  private RequestBodies requestBodies;

  @Before
  public void setUp() {
    objectMapper = new ObjectMapper();
    restTemplate = new TestRestTemplate();
    requestBodies = RequestBodies.single();
  }

  /**
   * 进入注册页面，检查注册页面是否被正确加载。
   */
  @Test
  public void registerUrlSuccess() throws IOException {
    try (final WebClient webClient = new WebClient()) {
      final HtmlPage registerPage = webClient.getPage(REGISTER_URL);
      assertThat(registerPage.getTitleText()).isEqualTo("Register Your Account");
      assertThat(registerPage.getCharset()).isEqualTo(StandardCharsets.UTF_8);
    }
  }

  /**
   * 测试用户注册成功的情景
   */
  @Test
  public void registerSuccess() throws JsonProcessingException {
    RegisterRequest registerRequest = requestBodies.randomValidRegisterRequest();

    log.info("{}", objectMapper.writeValueAsString(registerRequest));

    ResponseEntity<Account> responseEntity = restTemplate.postForEntity(
        REGISTER_URL, registerRequest, Account.class);

    assertThat(responseEntity).isNotNull();

    assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.CREATED);
    assertThat(responseEntity.getBody()).isNotNull();

    Account responseObject = responseEntity.getBody();
    assertThat(responseObject.getId()).isNotNull().isPositive();
    assertThat(responseObject.getUsername()).isEqualTo(registerRequest.getUsername());
  }

  /**
   * 测试用户名为空的情景
   */
  @Test
  public void registerFailWithEmptyUsername() {
    RegisterRequest registerRequest = requestBodies.randomValidRegisterRequest();
    registerRequest.setUsername(StringUtils.EMPTY); // Empty Username

    ResponseEntity<VndErrors> responseEntity = restTemplate.postForEntity(
        REGISTER_URL, registerRequest, VndErrors.class);

    assertThat(responseEntity).isNotNull();

    assertThat(responseEntity.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST);
    assertThat(responseEntity.getBody()).isNotNull();

    VndErrors responseObject = responseEntity.getBody();
    log.info("{}", responseObject);
    assertThat(responseObject).isNotNull();
  }

  /**
   * TODO: 作业：测试用户名太短的场景
   */
  @Test
  public void registerFailWithUsernameTooShort() {
    // add your code here
  }

  /**
   * TODO: 作业：测试用户名太长的场景
   */
  @Test
  public void registerFailWithUsernameTooLong() {
    // add your code here
  }

  /**
   * TODO： 作业：试密码不符合要求的场景
   */
  @Test
  public void registerFailWithInsufficientPasswordRequirement() {
    // add your code here
  }

  /**
   * TODO: 作业：测试用户名已被占用的场景
   */
  @Test
  public void registerFailWithUserAlreadyExists() {
    // add your code here
  }
}
